<template>
    <div class="height">
        <el-row class="height">
            <el-col :span="8" class="height">
                <title-box title="Element-Tree--oldTree-->未修改">
                    <el-tree ref="oldTree"
                             :data="data"
                             :props="defaultProps"
                             node-key="id"
                             :default-expand-all="true"
                             :expand-on-click-node="false"
                             :show-checkbox="true">
                    <span class="el-tree-node__label" slot-scope="{ node, data }">
                        <span> <i :class="data.icon"></i> </span>
                        <span> {{ data.name}}</span>
                    </span>
                    </el-tree>
                </title-box>
            </el-col>
            <el-col :span="8" class="height">
                <el-row class="height">
                    <el-col :span="24" class="json-view">
                        <title-box title="原始数据(sourceList)">
                            <json-viewer :value="sourceList" :expand-depth="2" copyable></json-viewer>
                        </title-box>
                    </el-col>
                    <el-col :span="24" class="json-view">
                        <title-box title="树数据">
                            <json-viewer :value="data" :expand-depth="2" copyable></json-viewer>
                        </title-box>
                    </el-col>
                    <el-col :span="12" class="json-view">
                        <title-box title="默认显示选中数据">
                            <json-viewer :value="checkData" :expand-depth="2" copyable></json-viewer>
                        </title-box>
                    </el-col>
                    <el-col :span="12" class="json-view">
                        <title-box title="操作按钮">
                            <div style="margin: 10px">
                                <el-button @click="showData">显示默认数据</el-button>
                                <el-button @click="clear">清除</el-button>
                            </div>
                            <div style="margin: 10px">
                                <el-button @click="saveNewTree">保存newTree数据并显示到oldTree</el-button>
                            </div>
                        </title-box>
                    </el-col>
                </el-row>
            </el-col>
            <el-col :span="8" class="height">
                <title-box title="Element-Tree--newTree-->修改后">
                    <el-tree ref="newTree"
                             :data="data"
                             :props="defaultProps"
                             node-key="id"
                             :default-expand-all="true"
                             :expand-on-click-node="false"
                             :show-checkbox="true"
                             @node-click="newTreeClick">
                    <span class="el-tree-node__label" slot-scope="{ node, data }">
                        <span> <i :class="data.icon"></i> </span>
                        <span> {{ data.name}}</span>
                    </span>
                    </el-tree>
                </title-box>
            </el-col>
        </el-row>
    </div>
</template>

<script>
    import TitleBox from "./components/TitleBox";
    import JsonViewer from 'vue-json-viewer'

    export default {
        name: "TreeDemo",
        components: {
            TitleBox, JsonViewer
        },
        props: {
            defaultProps: {
                type: Object,
                default: function () {
                    return {
                        children: 'children',
                        label: 'name'
                    }
                }
            },
        },
        data() {
            return {
                data: [],
                treeMap: {},
                sourceList: [
                    {"id": 2, "name": "日志记录", "icon": "el-icon-menu", "pid": null},
                    {"id": 3, "name": "登录日志", "icon": "el-icon-s-help", "pid": 2},
                    {"id": 4, "name": "异常日志", "icon": "el-icon-document-delete", "pid": 2},
                    {"id": 27, "name": "资金管理", "icon": "el-icon-money", "pid": null},
                    {"id": 25, "name": "礼金查询", "icon": "el-icon-money", "pid": 27},
                    {"id": 74, "name": "子菜单", "icon": null, "pid": 25},
                    {"id": 28, "name": "人情资金来往", "icon": "el-icon-user", "pid": 27},
                    {"id": 75, "name": "子菜单", "icon": null, "pid": 28},
                    {"id": 82, "name": "浏览器主页", "icon": "el-icon-picture-outline-round", "pid": null},
                    {"id": 83, "name": "效果演示", "icon": "el-icon-picture-outline-round", "pid": 82},
                    {"id": 84, "name": "书签设置", "icon": "el-icon-s-management", "pid": 82},
                    {"id": 92, "name": "子菜单", "icon": null, "pid": 84},
                    {"id": 93, "name": "密码本", "icon": "el-icon-notebook-1", "pid": null},
                    {"id": 95, "name": "子菜单", "icon": null, "pid": 93},
                    {"id": 97, "name": "数据视图", "icon": "el-icon-s-marketing", "pid": null},
                    {"id": 99, "name": "子菜单", "icon": null, "pid": 97},
                    {"id": 9, "name": "UI/组件", "icon": "el-icon-view", "pid": 0},
                    {"id": 7, "name": "默认页面布局", "icon": "el-icon-s-operation", "pid": 9},
                    {"id": 10, "name": "第三方页面显示", "icon": "el-icon-position", "pid": 9},
                    {"id": 14, "name": "Element-图标库", "icon": "el-icon-eleme", "pid": 9},
                    {"id": 16, "name": "数据表格", "icon": "el-icon-files", "pid": 9},
                    {"id": 73, "name": "数据树", "icon": "el-icon-tickets", "pid": 9},
                    {"id": 8, "name": "系统监控", "icon": "el-icon-s-operation", "pid": 0},
                    {"id": 11, "name": "Api文档", "icon": "el-icon-document", "pid": 8},
                    {"id": 12, "name": "系统健康", "icon": "el-icon-film", "pid": 8},
                    {"id": 17, "name": "定时任务", "icon": "el-icon-time", "pid": 8},
                    {"id": 100, "name": "子菜单", "icon": null, "pid": 17},
                    {"id": 18, "name": "接口请求统计", "icon": "el-icon-data-line", "pid": 8},
                    {"id": 5, "name": "系统设置", "icon": "el-icon-setting", "pid": 0},
                    {"id": 6, "name": "菜单管理", "icon": "el-icon-s-operation", "pid": 5},
                    {"id": 76, "name": "子菜单", "icon": null, "pid": 6},
                    {"id": 15, "name": "用户管理", "icon": "el-icon-user", "pid": 5},
                    {"id": 77, "name": "子菜单", "icon": null, "pid": 15},
                    {"id": 19, "name": "数据字典", "icon": "el-icon-s-management", "pid": 5},
                    {"id": 78, "name": "子菜单", "icon": null, "pid": 19},
                    {"id": 29, "name": "部门设置", "icon": "el-icon-chat-dot-round", "pid": 5},
                    {"id": 79, "name": "子菜单", "icon": null, "pid": 29},
                    {"id": 30, "name": "用户分组", "icon": "el-icon-user-solid", "pid": 5},
                    {"id": 80, "name": "子菜单", "icon": null, "pid": 30},
                    {"id": 71, "name": "权限控制", "icon": "el-icon-switch-button", "pid": 5},
                    {"id": 81, "name": "子菜单", "icon": null, "pid": 71},
                    {"id": 1, "name": "系统测试", "icon": "el-icon-thumb", "pid": null}
                ],
                checkData: ["2", "3", "4", "27", "28", "75", "82", "83", "84", "92", "97", "99", "9", "14", "8", "11", "12", "17", "100", "18", "5", "6", "76", "15", "77", "19", "78", "29", "79", "30", "80", "71", "81"],
                mouseY: 0,
                mouseX: 0
            }
        },
        methods: {
            newTreeClick(data) {
                this.$refs.newTree.setChecked(data.id, true, false);
                this.findParent(data.pid);
            },
            saveNewTree(){
                let arr = [];
                try {
                    arr = this.$refs.newTree.getCheckedKeys();
                    //拼接半选状态
                    arr = arr.concat(this.$refs.newTree.getHalfCheckedKeys())
                } catch (e) {
                    this.$message.error("为空,无需保存!");
                    return;
                }
                if(!arr.length){
                    this.$message.info("未选中数据");
                    return;
                }
                this.checkData = arr;
                this.showData();
            },
            findParent(pid) {
                if (this.treeMap[pid]) {
                    this.$refs.newTree.setChecked(pid, true, false);
                    let parentMap = this.treeMap[pid];
                    //向上查找
                    if (parentMap && parentMap["pid"]) {
                        this.findParent(parentMap["pid"]);
                    }
                }
            },
            arrToTree(arr) {
                let result = [];
                if (!Array.isArray(arr)) {
                    return result;
                }
                let map = {};
                arr.forEach(item => {
                    delete item.children;
                    map[item.id] = item;
                });
                arr.forEach(item => {
                    let parent = map[item.pid];
                    if (parent) {
                        (parent.children || (parent.children = [])).push(item);
                    } else {
                        result.push(item);
                    }
                });
                return result;
            },
            copyArrayObject(obj) {
                let newObj = obj.constructor === Array ? [] : {};
                if (typeof obj !== 'object') {
                    return;
                }
                for (let i in obj) {
                    if (obj[i]) {
                        newObj[i] = typeof obj[i] === 'object' ? this.copyArrayObject(obj[i]) : obj[i];
                    }
                }
                return newObj
            },
            showData() {
                this.clear();
                this.$message({
                    message: '同样的数据,由于存在父节点数据 oldTree就会将子节点全部选中; newTree就不会',
                    duration: 5000
                });

                //修改前展示数据
                this.$refs.oldTree.setCheckedKeys(this.checkData);
                //修改后展示数据
                this.checkData.forEach(id => {
                    this.$refs.newTree.setChecked(parseInt(id), true, false);
                    this.findParent(id);
                });
            },
            clear() {
                this.$refs.oldTree.setCheckedKeys([]);
                this.$refs.newTree.setCheckedKeys([]);
            },
            scrollRight() {
                let right = this.$refs.newTree.$el.parentElement;
                if(this.checkMouseXY(right)){
                    this.scroll(right.scrollTop);
                }
            },
            scrollLeft() {
                let left = this.$refs.oldTree.$el.parentElement;
                if(this.checkMouseXY(left)){
                    this.scroll(left.scrollTop);
                }
            },
            scroll(y) {
                let right = this.$refs.newTree.$el.parentElement;
                let left = this.$refs.oldTree.$el.parentElement;
                right.scrollTop = y;
                left.scrollTop = y;
            },
            mousewheel(e){
                this.mouseY = e.clientY;
                this.mouseX = e.clientX;
            },
            checkMouseXY(el){
                if(this.mouseX>el.offsetLeft && this.mouseX < (el.offsetLeft+el.clientWidth)){
                    return true;
                }else{
                    return false;
                }
            }
        },
        mounted() {
            let data = this.copyArrayObject(this.sourceList);
            this.data = this.arrToTree(data.concat());
            for (let i in data) {
                this.treeMap[data[i].id] = Object.assign({}, data[i]);
                if (this.treeMap[data[i].pid]) {
                    this.treeMap[data[i].pid].children = Object.assign({}, data[i]);
                }
            }

            this.$refs.newTree.$el.parentElement.addEventListener('scroll', this.scrollRight);
            this.$refs.newTree.$el.parentElement.addEventListener('mousewheel', this.mousewheel);
            this.$refs.oldTree.$el.parentElement.addEventListener('mousewheel', this.mousewheel);
            this.$refs.oldTree.$el.parentElement.addEventListener('scroll', this.scrollLeft);
        }
    }
</script>

<style>
    .height {
        height: 100%;
    }

    html, body {
        margin: 0;
        padding: 0;
        height: 100%;
    }

    .json-view {
        height: 33.33%;
    }
</style>